package com.xxxx.springbootsecurity02.util;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.util.Date;

public class JwtUtil {

    // 设置秘钥明文
    private static final String JWT_KEY_STRING = "hongzhuoThisIsAVeryLongSecretKeyThatIsAtLeast64CharactersLong1234567890";
    // 默认有效期为1小时 (3600000 毫秒)
    private static final long DEFAULT_TTL_MILLIS = 60 * 60 * 1000L;

    /**
     * 生成加密后的秘钥 secretKey
     * @return 返回HMAC-SHA算法所需的SecretKey
     */
    public static SecretKey generalKey() {
        // 确保密钥长度符合要求，如果不够会自动补齐
        return Keys.hmacShaKeyFor(JWT_KEY_STRING.getBytes());
    }

    /**
     * 生成JWT
     * @param subject token中要存放的数据
     * @return JWT字符串
     */
    public static String createJWT(String subject) {
        return createJWT(null, subject, DEFAULT_TTL_MILLIS);
    }

    /**
     * 生成JWT
     * @param subject token中要存放的数据
     * @param ttlMillis token超时时间
     * @return JWT字符串
     */
    public static String createJWT(String subject, Long ttlMillis) {
        return createJWT(null, subject, ttlMillis);
    }

    /**
     * 创建token
     * @param id 令牌ID
     * @param subject token中要存放的数据
     * @param ttlMillis token超时时间
     * @return JWT字符串
     */
    public static String createJWT(String id, String subject, Long ttlMillis) {
        // 如果未提供过期时间，使用默认值
        long expiration = (ttlMillis == null) ? DEFAULT_TTL_MILLIS : ttlMillis;
        Date now = new Date();
        Date expDate = new Date(now.getTime() + expiration);

        JwtBuilder builder = Jwts.builder()
                .setSubject(subject) // 主题，存放数据
                .setIssuedAt(now) // 签发时间
                .setExpiration(expDate) // 过期时间
                .signWith(generalKey()); // 签名密钥

        // 如果提供了id，设置令牌ID
        if (id != null && !id.trim().isEmpty()) {
            builder.setId(id);
        }

        return builder.compact();
    }

    /**
     * 解析JWT
     * @param jwt JWT字符串
     * @return Claims对象，包含解析出的声明
     * @throws Exception 解析失败时抛出异常
     */
    public static Claims parseJWT(String jwt) throws Exception {
        try {
            return Jwts.parser()
                    .verifyWith(generalKey()) // 验证签名
                    .build()
                    .parseSignedClaims(jwt)
                    .getPayload();
        } catch (ExpiredJwtException e) {
            throw new Exception("JWT已过期", e);
        } catch (UnsupportedJwtException e) {
            throw new Exception("不支持的JWT格式", e);
        } catch (MalformedJwtException e) {
            throw new Exception("JWT格式错误", e);
        } catch (SecurityException e) {
            throw new Exception("JWT签名验证失败", e);
        } catch (IllegalArgumentException e) {
            throw new Exception("JWT参数错误", e);
        }
    }

    // 测试方法
    public static void main(String[] args) throws Exception {
//        String token = createJWT("1001");
//        System.out.println(token);
//        Claims claims = JwtUtil.parseJWT("eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxMDAxIiwiaWF0IjoxNzU4NjE4OTg3LCJleHAiOjE3NTg2MjI1ODd9.fhGRni1pBXQV5WiKbiCG3upbmhAsTfDS_sNcmC4rLHNr-zy2n89ts1lHXsMLrADm4AJ9pyn6M62ikezgrTZTgA");
//        System.out.println(claims.getSubject());
    }

}
